#ifndef _CRT_COND_H_
#define _CRT_COND_H_

#include <crt_core.hpp>

#ifdef __cplusplus
extern "C" {
#endif

/*
 ==> _cond_timedwait = 1  	use CLOCK_MONOTONIC
 ==> _cond_timedwait = 0 	use CLOCK_REALTIME
*/

#define WAIT_TIME_RELATIVE 1
#define WAIT_TIME          0

#if (TARGET_OS == OS_WIN)

typedef struct {
    int process_shared;
    int relative;
    atomic_type waiting;
    atomic_type nsignal;
    _sem_t wait_sem;
    _sem_t wait_done;
    _mutex_t lock;
} _cond_t;

#elif (TARGET_OS == OS_POSIX)

typedef struct {
    int process_shared;
    int relative;
    pthread_condattr_t attr;
    pthread_cond_t c;
    pthread_mutex_t mutex;
} _cond_t;

#elif (TARGET_OS == OS_MACH)

typedef struct {
    int process_shared;
    int relative;
    pthread_condattr_t attr;
    pthread_cond_t c;
    pthread_mutex_t mutex;
} _cond_t;

#elif (TARGET_OS == OS_UNIX)

typedef struct {
    int process_shared;
    int relative;
    pthread_condattr_t attr;
    pthread_cond_t c;
    pthread_mutex_t mutex;
} _cond_t;

#endif

/* Wait on the condition variable for at most 'ms' milliseconds.
   The mutex must be locked before entering this function!
   The mutex is unlocked during the wait, and locked again after the wait.
Typical use:

Thread A:
    LockMutex(lock);
    while ( ! condition ) {
        CondWait(cond, lock);
    }
    UnlockMutex(lock);


Thread B:
    LockMutex(lock);
    ...
    condition = true;
    ...
    CondSignal(cond);
    UnlockMutex(lock);

 */

int _cond_init(_cond_t* cond);
int _cond_destroy(_cond_t* cond);
int _cond_signal(_cond_t* cond);
int _cond_broadcast(_cond_t* cond);
int _cond_wait(_cond_t* cond);
int _cond_timedwait(_cond_t* cond, unsigned long ms);

#ifdef __cplusplus
}
#endif

#endif
